package de.hsmannheim.poolraumapp.fragment;

import java.util.Locale;
import java.util.Observable;
import java.util.Observer;

import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.joda.time.format.DateTimeFormat;

import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.DatePicker;
import android.widget.DatePicker.OnDateChangedListener;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TimePicker;
import de.hsmannheim.poolraumapp.PoolraumApp;
import de.hsmannheim.poolraumapp.R;
import de.hsmannheim.poolraumapp.activity.DetailActivity;
import de.hsmannheim.poolraumapp.activity.NavigationActivity;
import de.hsmannheim.poolraumapp.model.RoomQuery;
import de.hsmannheim.poolraumapp.model.RoomQuery.WhenDay;
import de.hsmannheim.poolraumapp.model.RoomQuery.WhenTime;

/**
 * A fragment representing a single Item detail screen. This fragment is either
 * contained in a {@link NavigationActivity} in two-pane mode (on tablets) or a
 * {@link DetailActivity} on handsets.
 */
public class WhenFragment extends PoolraumFragment implements OnItemSelectedListener, OnDateChangedListener, OnCheckedChangeListener, OnClickListener, Observer{
		
	private static final String TAG = WhenFragment.class.getName();
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		Log.d(TAG, "creating WhenFragment");
		super.onCreate(savedInstanceState);
		Log.d(TAG, "WhenFragment created");
	}
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		Log.d(TAG, "inflating WhenFragment view");		
		View view = inflater.inflate(R.layout.fragment_when, container, false);		
		Log.d(TAG, "WhenFragment view inflated");
		
		RoomQuery roomQuery = getRoomQuery();		
											
		ArrayAdapter<CharSequence> weekdaysAdapter = ArrayAdapter.createFromResource(getActivity(), R.array.when_day_weekdays, android.R.layout.simple_spinner_item);
		weekdaysAdapter.setDropDownViewResource(android.R.layout.simple_spinner_item);
		
		Spinner weekdays = (Spinner)view.findViewById(R.id.when_day_weekdays);
		weekdays.setAdapter(weekdaysAdapter);
		weekdays.setSelection(roomQuery.getWeekday() - 1);
		weekdays.setOnItemSelectedListener(this);
		Log.d(TAG, "Weekdays initialized");
		
		Button dateButton = setDate(view, R.id.when_day_date_button, roomQuery.getDate());		
		dateButton.setOnClickListener(this);
		
		Button timePointButton = setTime(view, R.id.when_time_point_button, roomQuery.getTimePoint());		
		timePointButton.setOnClickListener(this);
		
		Button fromButton = setTime(view, R.id.when_time_span_from_button, roomQuery.getFrom());		
		fromButton.setOnClickListener(this);
		
		Button toButton = setTime(view, R.id.when_time_span_to_button, roomQuery.getTo());		
		toButton.setOnClickListener(this);
		
		setCheckedDay(view, getId(roomQuery.getDay()));
		setCheckedTime(view, getId(roomQuery.getTime()));
		
		((RadioButton)view.findViewById(R.id.when_day_today)).setOnCheckedChangeListener(this);
		((RadioButton)view.findViewById(R.id.when_day_weekday)).setOnCheckedChangeListener(this);
		((RadioButton)view.findViewById(R.id.when_day_date)).setOnCheckedChangeListener(this);	
		
		((RadioButton)view.findViewById(R.id.when_time_now)).setOnCheckedChangeListener(this);
		((RadioButton)view.findViewById(R.id.when_time_point)).setOnCheckedChangeListener(this);
		((RadioButton)view.findViewById(R.id.when_time_span)).setOnCheckedChangeListener(this);
		
		roomQuery.addObserver(this);
		
		return view;
	}	
	
	@Override
	public void onDestroyView() {	
		super.onDestroyView();
		getRoomQuery().deleteObserver(this);
	}

	private Button setDate(View view, int id, LocalDate date) {
		Button dateButton = (Button)view.findViewById(id);
		dateButton.setText(DateTimeFormat.forStyle("M-").withLocale(Locale.getDefault()).print(date));
		return dateButton;
	}
	
	private Button setTime(View view, int id, LocalTime time) {
		Button timeButton = (Button)view.findViewById(id);
		timeButton.setText(DateTimeFormat.forStyle("-S").withLocale(Locale.getDefault()).print(time));
		return timeButton;
	}

	private void setCheckedDay(View view, int id) {
		Log.d(TAG, "Enabling and disabling date views");
		((RadioButton)view.findViewById(R.id.when_day_today)).setChecked(id == R.id.when_day_today);
		((RadioButton)view.findViewById(R.id.when_day_weekday)).setChecked(id == R.id.when_day_weekday);
		((RadioButton)view.findViewById(R.id.when_day_date)).setChecked(id == R.id.when_day_date);
		view.findViewById(R.id.when_day_weekdays).setEnabled(id == R.id.when_day_weekday);
		view.findViewById(R.id.when_day_date_button).setEnabled(id == R.id.when_day_date);
		Log.d(TAG, "Date views enabled and disabled");
	}
	
	private void setCheckedTime(View view, int id) {
		Log.d(TAG, "Enabling and disabling time views");
		((RadioButton)view.findViewById(R.id.when_time_now)).setChecked(id == R.id.when_time_now);
		((RadioButton)view.findViewById(R.id.when_time_point)).setChecked(id == R.id.when_time_point);
		((RadioButton)view.findViewById(R.id.when_time_span)).setChecked(id == R.id.when_time_span);
		view.findViewById(R.id.when_time_point_button).setEnabled(id == R.id.when_time_point);
		view.findViewById(R.id.when_time_span_from_button).setEnabled(id == R.id.when_time_span);
		view.findViewById(R.id.when_time_span_to).setEnabled(id == R.id.when_time_span);
		view.findViewById(R.id.when_time_span_to_button).setEnabled(id == R.id.when_time_span);
		Log.d(TAG, "Time views enabled and disabled");
	}
	
	@Override
	public void onCheckedChanged(CompoundButton button, boolean checked) {
		if (checked) {
			int checkedId = button.getId();
			RoomQuery roomQuery = getRoomQuery();				
			switch (checkedId) {
				case R.id.when_day_today:
				case R.id.when_day_weekday:
				case R.id.when_day_date:
					roomQuery.setDay(getWhenDate(checkedId));
					setCheckedDay(getView(), checkedId);
					break;
				case R.id.when_time_now:
				case R.id.when_time_point:
				case R.id.when_time_span:
					roomQuery.setTime(getWhenTime(checkedId));
					setCheckedTime(getView(), checkedId);
					break;
			}
		}
	}
	
	private WhenDay getWhenDate(int id) {
		switch (id) {
			case R.id.when_day_today:	
				return WhenDay.TODAY; 
			case R.id.when_day_weekday:
				return WhenDay.WEEKDAY;
			case R.id.when_day_date:	
				return WhenDay.DATE;
		}
		throw new RuntimeException();
	}

	private int getId(WhenDay whenDate) {
		switch (whenDate) {
			case TODAY:	
				return R.id.when_day_today; 
			case WEEKDAY:
				return R.id.when_day_weekday;
			case DATE:	
				return R.id.when_day_date;
		}
		throw new RuntimeException();
	}
	
	private WhenTime getWhenTime(int id) {
		switch (id) {
			case R.id.when_time_now:	
				return WhenTime.NOW; 
			case R.id.when_time_point:
				return WhenTime.POINT;
			case R.id.when_time_span:	
				return WhenTime.SPAN;
		}
		throw new RuntimeException();
	}

	private int getId(WhenTime whenTime) {
		switch (whenTime) {
			case NOW:	
				return R.id.when_time_now; 
			case POINT:
				return R.id.when_time_point;
			case SPAN:	
				return R.id.when_time_span;
		}
		throw new RuntimeException();
	}

	@Override
	public void onItemSelected(AdapterView<?> adapter, View view, int position,
			long id) {
		getRoomQuery().setWeekday(position + 1);
	}

	@Override
	public void onNothingSelected(AdapterView<?> arg0) {
	}
	
	@Override
	public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
		getRoomQuery().setDate(new LocalDate(year, monthOfYear + 1, dayOfMonth));
	}

	@Override
	public void onClick(final View clicked) {
		switch (clicked.getId()) {
			case R.id.when_day_date_button:
				DateDialogFragment dateDialogFragment = new DateDialogFragment();
				dateDialogFragment.show(getActivity().getSupportFragmentManager(), "when_day_date_dialog");
				return;
			case R.id.when_time_point_button:
				TimeDialogFragment timePointDialogFragment = new TimePointDialogFragment();
				timePointDialogFragment.show(getActivity().getSupportFragmentManager(),"when_time_point_dialog");
				break;
			case R.id.when_time_span_from_button:
				TimeDialogFragment timeSpanFromDialogFragment = new FromDialogFragment();
				timeSpanFromDialogFragment.show(getActivity().getSupportFragmentManager(),"when_time_span_from_dialog");
				break;
			case R.id.when_time_span_to_button:
				TimeDialogFragment timeSpanToDialogFragment = new ToDialogFragment();
				timeSpanToDialogFragment.show(getActivity().getSupportFragmentManager(),"when_time_span_to_dialog");
				break;
		}	
	}

	public static class DateDialogFragment extends DialogFragment {
		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState) {
			final RoomQuery roomQuery = ((PoolraumApp)getActivity().getApplication()).getRoomQuery();
			return new DatePickerDialog(getActivity(), new DatePickerDialog.OnDateSetListener() {					
				@Override
				public void onDateSet(DatePicker view, int year, int monthOfYear,
						int dayOfMonth) {
					LocalDate newDate = new LocalDate(year, monthOfYear + 1, dayOfMonth);
					roomQuery.setDate(newDate);
				}
			}, 
			roomQuery.getDate().getYear(), 
			roomQuery.getDate().getMonthOfYear() - 1,
			roomQuery.getDate().getDayOfMonth());
		}
	}
	
	public static abstract class TimeDialogFragment extends DialogFragment {		
		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState) {
			final RoomQuery roomQuery = ((PoolraumApp)getActivity().getApplication()).getRoomQuery();
			LocalTime time = getTime(roomQuery);
			return new TimePickerDialog(getActivity(), new TimePickerDialog.OnTimeSetListener() {					
				@Override
				public void onTimeSet(TimePicker picker, int hour,
						int minutes) {
					LocalTime newTime = new LocalTime(hour, minutes, 0);
					setTime(roomQuery, newTime);
				}
			}, 
			time.getHourOfDay(), 
			time.getMinuteOfHour(),
			true);
		}
		
		protected abstract LocalTime getTime(RoomQuery roomQuery);

		protected abstract void setTime(RoomQuery roomQuery, LocalTime time);
	}
	
	public static class TimePointDialogFragment extends TimeDialogFragment {
		@Override
		protected LocalTime getTime(RoomQuery roomQuery) {
			return roomQuery.getTimePoint();
		}

		@Override
		protected void setTime(RoomQuery roomQuery, LocalTime time) {
			roomQuery.setTimePoint(time);			
		}		
	}
	
	public static class FromDialogFragment extends TimeDialogFragment {
		@Override
		protected LocalTime getTime(RoomQuery roomQuery) {
			return roomQuery.getFrom();
		}

		@Override
		protected void setTime(RoomQuery roomQuery, LocalTime time) {
			roomQuery.setFrom(time);			
		}		
	}
	
	public static class ToDialogFragment extends TimeDialogFragment {
		@Override
		protected LocalTime getTime(RoomQuery roomQuery) {
			return roomQuery.getTo();
		}

		@Override
		protected void setTime(RoomQuery roomQuery, LocalTime time) {
			roomQuery.setTo(time);			
		}		
	}

	@Override
	public void update(Observable observable, Object id) {
		RoomQuery roomQuery = getRoomQuery();
		if (observable == roomQuery) {
			if (id == RoomQuery.DATE) {
				setDate(getView(), R.id.when_day_date_button, roomQuery.getDate());
			} else if (id == RoomQuery.TIME_POINT) {
				setTime(getView(), R.id.when_time_point_button, roomQuery.getTimePoint());
			} else if (id == RoomQuery.FROM) {
				setTime(getView(), R.id.when_time_span_from_button, roomQuery.getFrom());
			} else if (id == RoomQuery.TO) {
				setTime(getView(), R.id.when_time_span_to_button, roomQuery.getTo());
			}
		}
	}
}
